// [参考](https://docs.mapbox.com/mapbox-gl-js/example/drag-a-point/)
import * as turf from "@turf/turf";
import EditBase from "./EditBase";
import { getEditIndex, toCentroidGeojson, toPointGeojson } from "./utils";

export default class EditScale extends EditBase {
	constructor(map) {
		super(map);

		this.editLayerId = "edit-scale-layer";

		this.centroid = null;
		this.editIndex = -1;

		this.initEditLayers();
	}

	initEditLayers() {
		const { map, editLayerId } = this;

		const editScaleLayer = {
			id: editLayerId,
			type: "symbol",
			source: {
				type: "geojson",
				data: {
					type: "FeatureCollection",
					features: [],
				},
			},
			layout: {
				"icon-image": ["get", "icon"],
				"icon-size": 1,
				// "icon-offset": [0, -20],
			},
			paint: {
				"icon-opacity": 1,
				"icon-halo-color": "red",
				"icon-halo-width": 10,
			},
		};

		map.addLayer(editScaleLayer);

		this.editSource = map.getSource(editLayerId);
	}

	onMouseDown(e) {
		// Prevent the default map drag behavior.
		e.preventDefault();

		const { canvas, map } = this;

		canvas.style.cursor = "grab";

		const zoom = map.getZoom();
		const radius = 10 / zoom; // 根据zoom设置半径
		this.editIndex = getEditIndex(this.points, e.lngLat, radius);

		if (this.editIndex > -1) {
			this.centroid = toCentroidGeojson(this.points);

			map.on("mousemove", this.moveFunc);
			map.once("mouseup", this.upFunc);
		}
	}

	onMove(callback, e) {
		const { canvas, points, editSource, centroid, editIndex } = this;

		if (editIndex < 0) return;

		canvas.style.cursor = "grabbing";

		const start = turf.point(points[editIndex]);
		const dist1 = turf.distance(centroid, start);

		const coords = e.lngLat;
		const end = turf.point([coords.lng, coords.lat]);
		const dist2 = turf.distance(centroid, end);

		const factor = dist2 / dist1;

		const newPoints = points.map((point) => {
			const source = turf.point(point);
			const dist = turf.distance(centroid, source) * factor;
			const bearing = turf.bearing(centroid, source);
			const target = turf.destination(centroid, dist, bearing);

			return target.geometry.coordinates;
		});

		const data = toPointGeojson(newPoints, { icon: "scale-icon" });
		editSource.setData(data);

		callback(newPoints);
	}

	updateEditSource(points) {
		const data = toPointGeojson(points, { icon: "scale-icon" });
		this.editSource.setData(data);

		this.points = points;
	}
}
